Görselleştirilmiş JavaScript: Scope (Zinciri)

Gizem Korkmaz
4 min readMay 6, 2022

Bu yazı Lydia Hallie’nin JavaScript Visualized: Scope (Chain) adlı makalesinin bir çevirisidir.

Sıra scope zincirinde🕺🏼

Bu yazıda, execution contextleri hakkında temeliniz olduğunu varsayıyorum. Yakında bununla ilgili de bir yazı yazacağım 😃

Aşağıdaki koda bir göz atalım:

const name = "Lydia"
const age = 21
const city = "San Francisco"


function getPersonInfo() {
const name = "Sarah"
const age = 22

return `${name} is ${age} and lives in ${city}`
}

console.log(getPersonInfo())

name, age ve city değişkenlerinin değerlerini içeren bir string döndüren getPersonInfo fonksiyonunu çağırıyoruz:

Sarah 22 yaşında ve San Francisco'da yaşıyor

Ama getPersonalInfo fonksiyonu city adında bir değişken içermiyordu 🤨 ? Nasıl oldu da city’nin değerini biliyor?

İlk olarak, farklı contextler için bellek alanı ayarlanır. Bir varsayılan global context’e (tarayıcıda window, Node’da global), bir de çalıştırılmış getPersonalInfo fonksiyonu için lokal bir context’e sahibiz. Her ikisinin de birer scope zinciri var.

getPersonInfo fonksiyonu için scope zinciri şuna benzer bir şekilde gözükür (endişelenmeyin, henüz bir anlam ifade etmesi gerekmiyor):

Scope zinciri temel olarak, mevcut execution context’de referans alınabilen değerlere (ve diğer scopelara) referanslar içeren objelere yönelik bir “referans zinciridir.” (⛓: “Hey, bu context içerisinde referans verebileceğiniz tüm değerler bunlar) Scope zinciri, execution context ile beraber oluşturulur. Bu demek oluyor ki çalışma zamanında oluşturulur!

Ancak, bu yazıda genel olarak activation objesinden ya da execution contextlerden bahsetmeyeceğim. Biz sadece scope’a odaklanalım! Aşağıdaki örneklerde, execution contextlerdeki key/value çiftleri, scope zincirinin sahip olduğu değişkenlerin referanslarını temsil eder.

Global execution context’in scope zincirinde 3 değişkene referans vardır: Lydia değerine sahip name, 21 değerine sahip age, San Francisco değerine sahip city. Lokal context’te ise 2 değişkene referansımız vardır: Sarah değerine sahip olan name ve 22 değerine sahip age.

getPersonInfo fonksiyonundaki değişkenlere erişmeye çalıştığımızda, motor ilk olarak lokal scope zincirini kontrol eder.

Lokal scope zincirinin name ve age referansı var! name Sarah değerine, age ise 22 değerine sahip. Peki ya city değerine ulaşmaya çalıştığında ne oluyor?

city’ye değer bulmak için motor, “scope zincirinde aşağı iner”. Bu, temelde motorun o kadar da kolay pes etmediği anlamına gelir: lokal scope’un referans aldığı dış kapsamda, yani mevcut durumda global objede,city değişkeni için bir değer bulup bulamayacağını görmeniz için çok çalışır.

Global context’te, city değişkenini San Francisco değeri ile tanımladık, bu nedenle city değişkenine bir referans var. Artık değişken için bir değerimiz olduğuna göre, getPersonInfo fonksiyonu Sarah 22 yaşında ve San Francisco'da yaşıyor string değerini döndürebilir. 🎉

Scope zincirinde aşağı inebiliriz ancak yukarı çıkamayız. Tamam, bu biraz kafa karıştırıcı olabilir çünkü bazı insanlar aşağı yerine yukarı diyor, bu yüzden yeniden ifade edeceğim: Dış scopelara gidebilirsiniz anca daha içe gidemezsiniz. Bunu bir tür şelale olarak görselleştirmeyi seviyorum:

Hatta daha da içe:

Bu koda örnek olarak bir bakalım:

Hemen hemen aynı gibi görünüyor ancak arada büyük bir fark var: city değişkenini şimdi global context’te değil getPersonInfo fonksiyonu içinde tanımladık. getPersonInfo fonksiyonunu çağırmadık, böylece lokal context de oluşturulmadı. Yine de name, age ve city değerlerine global context içinde erişmeye çalışıyoruz.

ReferenceError dönüyor! Global scope’da city adında bir değişkene referans bulamaz ve bakacak bir dış scope alanı da yok. Böylece scope zincirinde yukarıya çıkamaz.

Bu şekilde, scope’u değişkenlerinizi bir tür “koruma” yolu olarak kullanabilir ve değişken isimlerinizi tekrar kullanabilirsiniz.

Global ve lokal scopeların yanı sıra bir de block scope vardır. let ve const anahtar kelimeleri ile tanımlanmış değişkenler, en yakın küme parantezine ({ }) göre kapsamlandırılır.

const age = 21

function checkAge() {
if (age < 21) {
const message = "You cannot drink!"
return message
} else {
const message = "You can drink!"
return message
}
}

Bu scope’u şu şekilde görselleştirebilirsiniz:

Bir global scope, bir function scope ve iki block scope’umuz var. message değişken ismini iki kere kullanabildik, çünkü değişkenler küme parantezleri ile scope alanına alınmışlardı.

Hızlı bir özet:

  • “Scope zincirini” mevcut context içinde erişebileceğimiz değerlere referanslar zinciri olarak düşünebilirsiniz.
  • Scopelar ayrıca scope zincirinden daha aşağıda tanımlanan değişken adlarının yeniden kullanılmasını da mümkün kılar, çünkü scope zincirinde yukarı değil yalnızca aşağı inebilir.

Scope (zincirleri) bu kadar! Bu konuda söylenecek milyonlarca şey var, bu yüzden müsait zaman buldukça fazladan bilgiler ekleyebilirim. Herhangi bir şeyde zorlanıyorsanız soru sormaktan çekinmeyin, yarım etmeyi çok isterim! 💕

--

--